package controller

import (
	"encoding/json"
	"github.com/duke-git/lancet/v2/convertor"
	"github.com/gin-gonic/gin"
	"github.com/pkg/errors"
	"go.uber.org/zap"
	"kf/common"
	"kf/models/dao"
	"kf/models/entity"
	"kf/tools"
	"kf/utils/R"
	"kf/ws"
	"math/rand"
	"net/http"
	"strconv"
	"time"
)

type VisitorController struct {
	SysUserDao      *dao.SysUserDao
	VisitorDao      *dao.VisitorsDao
	ShoutController *ShoutController
	WsVisitor       *ws.WsVisitor
	MessageDao      *dao.MessageDao
	SysRuleDao      *dao.SysRuleDao
	Log             *zap.Logger
}

// 与客服沟通
func (visitorController *VisitorController) PostVisitorLogin(c *gin.Context) {
	ip := c.ClientIP()
	ipcity := tools.ParseIp(ip)
	avator := ""
	userAgent := c.GetHeader("User-Agent")
	if tools.IsMobile(userAgent) {
		avator = "/static/images/1.png"
	} else {
		avator = "/static/images/2.png"
	}
	//要对话的客服
	kefuId := c.PostForm("to_id")
	//客户信息
	visitorId := c.PostForm("visitor_id")
	//如果客户登陆了网站，则获取email、firstName、lastName
	email := c.PostForm("email")
	firstName := c.PostForm("firstName")
	lastName := c.PostForm("lastName")
	//生成客户的id，
	var hasLogin = email != "" && firstName != "" && lastName != ""
	//如果客户id不是前端传过来的，且客户没有登陆，则进行下面逻辑进行自动生成
	if visitorId == "" && !hasLogin {
		visitorId = tools.Uuid()
	}
	//如果登陆了，则用登陆的邮箱信息进行唯一化处理
	if hasLogin {
		visitorId = tools.StringToUUID(email)
	}
	refer := c.PostForm("refer")
	var (
		city string
		name string
	)
	if ipcity != "" {
		city = ipcity
		name = ipcity + "网友"
	} else {
		city = "未识别地区"
		name = "匿名网友"
	}
	extra := c.PostForm("extra")
	extraJson := tools.Base64Decode(extra)
	if extraJson != "" {
		var extraObj VisitorExtra
		err := json.Unmarshal([]byte(extraJson), &extraObj)
		if err == nil {
			if extraObj.VisitorName != "" {
				name = extraObj.VisitorName
			}
			if extraObj.VisitorAvatar != "" {
				avator = extraObj.VisitorAvatar
			}
		}
	}
	if name == "" || visitorId == "" || refer == "" || city == "" || ip == "" {
		c.JSON(200, gin.H{
			"code": 400,
			"msg":  "缺少必要的会话信息",
		})
		return
	}
	var kefuInfo entity.SysUser
	//查询数据库，看看对应客户是否已经绑定了某个客服
	//判断一下这个客户是否存在
	visitor := visitorController.VisitorDao.FindVisitorByVisitorId(visitorId)
	if visitor.VisitorId != "" {
		//客户存在的情况下，看下客服是否已经对应上了
		if visitor.ToId != "" {
			kefuId = visitor.ToId
		}
	}
	var err error
	//此处加逻辑，如果前端没有指定客服，或者后端逻辑中指定的客服不存在，则根据规则进行查询
	if kefuId == "" {
		host := c.Request.Host
		//根据host和ip，获取规则数据，根据规则找到客服
		hostIp := visitorController.SysRuleDao.GetSysRuleByHostIp(host, ip)
		if len(hostIp) > 0 {
			kefuId = hostIp[0]
		} else {
			if len(ws.KefuList) > 0 {
				// 初始化随机数种子
				rand.NewSource(time.Now().UnixNano())
				// 提取map的键到切片中
				keys := make([]string, 0, len(ws.KefuList))
				for k := range ws.KefuList {
					keys = append(keys, k)
				}
				// 生成一个随机索引
				randomIndex := rand.Intn(len(keys))
				// 使用随机索引从map中获取值
				randomKey := keys[randomIndex]
				randomValue := ws.KefuList[randomKey]
				kefuId = randomValue.Id
			}
		}
	}
	//如果在线客服是不存在的，那么就从所有的客服中找一个
	var kefeOnline = true
	if kefuId == "" {
		kefuInfo, err = visitorController.SysUserDao.FindSysUserRandom()
		kefuId = strconv.FormatUint(kefuInfo.ID, 10)
		kefeOnline = false
	} else {
		kefuInfo, err = visitorController.SysUserDao.FindSysUserById(kefuId)
	}
	if err != nil {
		visitorController.Log.Error("获取客服失败", zap.Error(errors.WithStack(err)))
		c.JSON(200, gin.H{
			"code": 400,
			"msg":  "客服不存在",
		})
		return
	}

	if visitor.Name != "" {
		avator = visitor.Avator
		//更新状态上线
		visitorController.VisitorDao.UpdateVisitor(name, visitor.Avator, visitorId, 1, ip, ip, refer, extra, kefuId)
	} else {
		//创建客户
		visitorController.VisitorDao.CreateVisitor(name, avator, ip, kefuId, visitorId, refer, city, ip, extra)
	}
	visitor.Name = name
	visitor.Avator = avator
	visitor.ToId = kefuId
	visitor.ClientIp = ip
	visitor.VisitorId = visitorId

	//通知客服，已有客户上线
	if kefeOnline {
		go visitorController.WsVisitor.VisitorOnline(strconv.FormatUint(kefuInfo.ID, 10), visitor)
	}
	c.JSON(200, gin.H{
		"code":   200,
		"msg":    "ok",
		"result": visitor,
	})
}

// 根据客户id查询客户
func (visitorController *VisitorController) GetVisitor(c *gin.Context) {
	visitorId := c.Query("visitorId")
	vistor := visitorController.VisitorDao.FindVisitorByVisitorId(visitorId)
	c.JSON(http.StatusOK, R.ReturnSuccess(vistor))
}

// @Summary 获取访客列表接口
// @Produce  json
// @Accept multipart/form-data
// @Param page query   string true "分页"
// @Param token header string true "认证token"
// @Success 200 {object} controller.Response
// @Failure 200 {object} controller.Response
// @Router /visitors [get]
func (visitorController *VisitorController) GetVisitorPage(c *gin.Context) {
	page, _ := strconv.Atoi(c.Query("page"))
	pagesize, _ := strconv.Atoi(c.Query("pagesize"))
	visitorId := c.Query("visitor_id")
	if pagesize == 0 {
		pagesize = int(common.VisitorPageSize)
	}
	kefuId, _ := c.Get("kefu_id")
	toInt := convertor.ToString(kefuId)
	if toInt == "1" || toInt == "2" {
		toInt = ""
	}
	vistors := visitorController.VisitorDao.FindVisitorsByKefuId(uint(page), uint(pagesize), toInt, visitorId)
	count := visitorController.VisitorDao.CountVisitorsByKefuId(toInt, visitorId)
	c.JSON(200, gin.H{
		"code": 200,
		"msg":  "ok",
		"data": gin.H{
			"list":     vistors,
			"count":    count,
			"pagesize": common.PageSize,
		},
	})
}

// @Summary 获取访客聊天信息接口
// @Produce  json
// @Accept multipart/form-data
// @Param visitorId query   string true "访客ID"
// @Param token header string true "认证token"
// @Success 200 {object} controller.Response
// @Failure 200 {object} controller.Response
// @Router /messages [get]
func (visitorController *VisitorController) GetVisitorMessage(c *gin.Context) {
	visitorId := c.Query("visitorId")

	query := "message.visitor_id= ?"
	messages := visitorController.MessageDao.FindMessageByWhere(query, visitorId)
	result := make([]map[string]interface{}, 0)
	for _, message := range messages {
		item := make(map[string]interface{})

		item["time"] = message.CreatedAt.Format("2006-01-02 15:04:05")
		item["content"] = message.Content
		item["mes_type"] = message.MesType
		item["visitor_name"] = message.VisitorName
		item["visitor_avator"] = message.VisitorAvator
		item["kefu_name"] = message.KefuName
		item["kefu_avator"] = message.KefuAvator
		result = append(result, item)

	}
	//异步修改消息已读
	go visitorController.MessageDao.ReadMessageByVisitorId(visitorId)
	c.JSON(200, gin.H{
		"code":   200,
		"msg":    "ok",
		"result": result,
	})
}

// @Summary 获取在线访客列表接口
// @Produce  json
// @Success 200 {object} controller.Response
// @Failure 200 {object} controller.Response
// @Router /visitors_online [get]
func (visitorController *VisitorController) GetVisitorOnlines(c *gin.Context) {
	users := make([]map[string]string, 0)
	visitorIds := make([]string, 0)
	for uid, visitor := range ws.ClientList {
		userInfo := make(map[string]string)
		userInfo["uid"] = uid
		userInfo["name"] = visitor.Name
		userInfo["avator"] = visitor.Avator
		users = append(users, userInfo)
		visitorIds = append(visitorIds, visitor.Id)
	}

	//查询最新消息
	messages := visitorController.MessageDao.FindLastMessage(visitorIds)
	temp := make(map[string]string, 0)
	for _, mes := range messages {
		temp[mes.VisitorId] = mes.Content
	}
	for _, user := range users {
		user["last_message"] = temp[user["uid"]]
	}

	tcps := make([]string, 0)
	for ip, _ := range clientTcpList {
		tcps = append(tcps, ip)
	}
	c.JSON(200, gin.H{
		"code": 200,
		"msg":  "ok",
		"result": gin.H{
			"ws":  users,
			"tcp": tcps,
		},
	})
}

// @Summary 获取客服的在线访客列表接口
// @Produce  json
// @Success 200 {object} controller.Response
// @Failure 200 {object} controller.Response
// @Router /visitors_kefu_online [get]
func (visitorController *VisitorController) GetKefusVisitorOnlines(c *gin.Context) {
	kefuId, _ := c.Get("kefu_id")
	users := make([]*VisitorOnline, 0)
	visitorIds := make([]string, 0)
	list := ws.ClientList
	for uid, visitor := range list {
		if visitor.ToId != convertor.ToString(kefuId) {
			continue
		}
		userInfo := new(VisitorOnline)
		userInfo.Uid = uid
		userInfo.Username = visitor.Name
		userInfo.Avator = visitor.Avator
		users = append(users, userInfo)
		visitorIds = append(visitorIds, visitor.Id)
	}

	//查询最新消息
	messages := visitorController.MessageDao.FindLastMessage(visitorIds)
	temp := make(map[string]entity.Message)
	for _, message := range messages {
		temp[message.VisitorId] = message
	}
	for _, user := range users {
		user.LastMessage = temp[user.Uid].Content
		if temp[user.Uid].Status == "read" || temp[user.Uid].MesType == "kefu" {
			user.HiddenNewMessage = true
		} else {
			user.HiddenNewMessage = false
		}
		if user.LastMessage == "" {
			user.LastMessage = "新访客"
		}
	}

	tcps := make([]string, 0)
	for ip, _ := range clientTcpList {
		tcps = append(tcps, ip)
	}
	c.JSON(http.StatusOK, R.ReturnSuccess(users))
}

// 删除客服客户的绑定
func (visitorController *VisitorController) DeleteBind(context *gin.Context) {
	id := context.Param("visitorId")
	err := visitorController.VisitorDao.DeleteBind(id)
	if err != nil {
		context.JSON(http.StatusOK, R.ReturnFailMsg(err.Error()))
		return
	}
	context.JSON(http.StatusOK, R.ReturnSuccess(nil))
}
